#include "CHIP_SPI_module/CHIP_SPI.hpp"

#ifdef DBG_TAG
#undef DBG_TAG
#endif
#ifdef DBG_LVL
#undef DBG_LVL
#endif

#define DBG_TAG     "CHIP_PWM"
#define DBG_LVL     DBG_LOG

extern "C"
{
#include <rtdbg.h>
}

using namespace std;

/******************************************************************************
 *
 * @brief:     CHIP_SPI类实现
 *
 ******************************************************************************/

CHIP_SPI::CHIP_SPI(std::string spi_name,
                   std::string dev_name,
                   uint16_t cs_pin,
                   GPIO_TypeDef * cs_port,
                   uint8_t data_width,
                   uint32_t max_hz,
                   uint8_t mode)
{
    struct rt_spi_configuration spi_cfg;
    struct rt_spi_device *spi;

    spi_cfg.data_width = data_width;
    spi_cfg.max_hz = max_hz;
    spi_cfg.mode = mode;

    //查找spi总线
    spi = (struct rt_spi_device *) rt_device_find(spi_name.c_str());
    if (!spi)
    {
        LOG_E("create error: spi bus <%s> isn't exist", spi_name.c_str());
        init_flag = chip_spi_status_fail;
        return;
    }

    // 将设备添加到 SPI总线
    spi_device = (struct rt_spi_device *) rt_device_find(dev_name.c_str());
    if (!spi_device)
        rt_hw_spi_device_attach(spi_name.c_str(), dev_name.c_str(), cs_port, cs_pin);
    else
        LOG_W("<%s> device already on spi bus <%s>", dev_name.c_str(), spi_name.c_str());

    // 查找 spi 设备获取设备句柄
    spi_device = (struct rt_spi_device *) rt_device_find(dev_name.c_str());
    if (!spi_device)
    {
        LOG_E("create error:can't find <%s> device", dev_name.c_str());
        init_flag = chip_spi_status_fail;
        return;
    }

    /* 设置设备通信模式*/
    if (rt_spi_configure(spi_device, &spi_cfg) != RT_EOK)
    {
        LOG_E("create error:can't configure <%s> device", dev_name.c_str());
        init_flag = chip_spi_status_fail;
        return;
    }

    this->spi_name = spi_name;
    this->dev_name = dev_name;
    this->data_width = data_width;
    this->max_hz = max_hz;
    this->mode = mode;

    LOG_I("init spi device :<%s> on spi:<%s> create ok ", dev_name.c_str(), spi_name.c_str());
    init_flag = chip_spi_status_ok;
    debug_flag = 0;

}
CHIP_SPI::~CHIP_SPI()
{

}

void CHIP_SPI::CHIP_SPI_open_debug()
{
    debug_flag = 1;
}
void CHIP_SPI::CHIP_SPI_close_debug()
{
    debug_flag = 0;
}

chip_spi_status CHIP_SPI::CHIP_SPI_read_status()
{
    return init_flag;
}
void CHIP_SPI::CHIP_SPI_send_uint8(uint8_t send_data)
{

    struct rt_spi_message msg1;
    if (init_flag == chip_spi_status_ok)
    {
        msg1.send_buf = &send_data;
        msg1.recv_buf = RT_NULL;
        msg1.length = 1;
        msg1.cs_take = 1;
        msg1.cs_release = 0;
        msg1.next = RT_NULL;

        rt_spi_transfer_message(spi_device, &msg1);

        if (debug_flag)
        {
            LOG_D("for this time trans");
            LOG_D("send buff <0x%.2X>", send_data);
        }
    }
}
void CHIP_SPI::CHIP_SPI_send_uint8_array(uint8_t* send_buff, size_t buff_size)
{
    rt_size_t send_ok_num;
    if (init_flag == chip_spi_status_ok)
    {
        if (!send_buff) return;
        send_ok_num = rt_spi_send(spi_device, send_buff, buff_size);
        if (send_ok_num != buff_size)
        LOG_W("<%s> spi send buff fail", dev_name.c_str());

        if (debug_flag)
        {
            LOG_D("for this time trans");
            for (size_t i = 0; i < buff_size; i++)
                LOG_D("send buff <0x%.2X>", send_buff[i]);

        }
    }
}

void CHIP_SPI::CHIP_SPI_send_uint8_and_read_uint8(uint8_t send_buff, uint8_t *read_buff)
{
    struct rt_spi_message msg1, msg2;
    if (init_flag == chip_spi_status_ok)
    {
        msg1.send_buf = &send_buff;
        msg1.recv_buf = RT_NULL;
        msg1.length = 1;
        msg1.cs_take = 1;
        msg1.cs_release = 0;
        msg1.next = &msg2;

        msg2.send_buf = RT_NULL;
        msg2.recv_buf = read_buff;
        msg2.length = 1;
        msg2.cs_take = 0;
        msg2.cs_release = 1;
        msg2.next = RT_NULL;

        rt_spi_transfer_message(spi_device, &msg1);
        if (debug_flag)
        {
            LOG_D("for this time trans and read");
            LOG_D("send buff <0x%.2X> read buff <0x%.2X>", send_buff, *(uint8_t* )read_buff);
        }
    }
}
void CHIP_SPI::CHIP_SPI_send_uint8_array_and_read_uint8_array(const void *send_buf,
                                                              size_t send_length,
                                                              void *recv_buf,
                                                              size_t recv_length)
{
    rt_err_t flag;
    uint32_t i;
    if (init_flag == chip_spi_status_ok)
    {
        flag = rt_spi_send_then_recv(spi_device, send_buf, send_length, recv_buf, recv_length);
        if (flag != RT_EOK)
        LOG_W("<%s> spi send and read buff fail", dev_name.c_str());
        if (debug_flag)
        {
            if (flag != RT_EOK) return;
            LOG_D("for this time trans");
            for (i = 0; i < send_length; i++)
            {
                LOG_D("send buff <0x%.2X>", *(uint8_t* )(send_buf + i));
            }
            for (i = 0; i < recv_length; i++)
            {
                LOG_D("read buff <0x%.2X>", *(uint8_t* )(recv_buf + i));
            }
        }
    }
}

void CHIP_SPI::CHIP_SPI_send_uint16(uint16_t send_data)
{
    CHIP_SPI_send_uint8(send_data >> 8);
    CHIP_SPI_send_uint8((uint8_t) send_data);
}
void CHIP_SPI::CHIP_SPI_send_uint16_array(uint16_t* send_buff, size_t buff_size)
{
    uint8_t *temp = NULL;
    if (!send_buff) return;
    if (init_flag == chip_spi_status_ok)
    {
        temp = (uint8_t*) rt_malloc(buff_size * 2);
        if (!temp)
        {
            LOG_E("no mem for sending uint16 array,dev <%s> ", dev_name.c_str());
            return;
        }

        for (size_t i = 0; i < buff_size; i++)
        {
            temp[i * 2] = send_buff[i] >> 8;
            temp[i * 2 + 1] = (uint8_t) send_buff[i];
        }
        CHIP_SPI_send_uint8_array(temp, buff_size * 2);
        rt_free(temp);
    }

}

